package es.techideas.appsjam;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import es.techideas.appsjam.model.AbstractModelElement;
import es.techideas.appsjam.model.AbstractModelElement.ContainerColor;
import es.techideas.appsjam.model.AnimationModelElement;
import es.techideas.appsjam.model.ContainerModelElement;

public class GameScene {

	private List<ContainerModelElement> containers;
	private List<AbstractModelElement> elements;
	private List<AnimationModelElement> animations;

	//	private int level;
	private AbstractModelElement selected;
	private GameView gameView;
	private Context context;

	protected volatile boolean gameOn;

	private Random rnd = new Random();
	
	private int estalviEuros = 0;
	private int gastCO2 = 0;
	private Handler handler;


	public GameScene(int level, Context context, GameView gameView, Handler handler){
		//		this.level = level;
		this.context = context;
		this.gameView = gameView;
		containers = new ArrayList<ContainerModelElement>();
		elements   = new ArrayList<AbstractModelElement>();
		animations   = new ArrayList<AnimationModelElement>();
		this.handler = handler;
	}

	public void initialize() {
		containers.add(new ContainerModelElement(context, gameView, ContainerColor.ORGANIC));
		containers.add(new ContainerModelElement(context, gameView, ContainerColor.PLASTICS));
		containers.add(new ContainerModelElement(context, gameView, ContainerColor.RESTA));
		containers.add(new ContainerModelElement(context, gameView, ContainerColor.VIDRE));
		containers.add(new ContainerModelElement(context, gameView, ContainerColor.PAPER));
		containers.add(new ContainerModelElement(context, gameView, ContainerColor.PUNT_VERD));

		for(AbstractModelElement ame : containers){
			ame.initialize();
		}
		for(AbstractModelElement ame : elements){
			ame.initialize();
		}

		gameOn = true;
		final GameScene scene = this;
		Runnable runnable = new Runnable() {

			@Override
			public void run() {
				int sleep = 2000;
				while(gameOn){
					scene.addElement();
					if(sleep > 500){
						sleep -= 10;
					}
					sleep(sleep);
				}
			}

			private void sleep(int i) {
				try {
					Thread.sleep(i);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}; 

		Thread worker = new Thread(runnable);
		worker.start();
		addElement();
	}

	protected void addElement() {
		synchronized (this) {
			AbstractModelElement element = new AbstractModelElement(context, gameView, getRandomContainerColor());
			element.initialize();
			elements.add(element);
			if(elements.size() > 20){
				gameOver();
			}	
		}
	}


	private void gameOver() {
		gameOn = false;
		selected = null;
		Message msg = new Message();
		Bundle bundle = new Bundle();
		bundle.putString("text", "GAME OVER!");
		bundle.putInt("viz", View.VISIBLE);
		msg.setData(bundle);
		handler.sendMessage(msg);
		for(AbstractModelElement a : elements){
			a.setVelocityX(-2000);
			a.setVelocityY(0);
		}
	}

	private ContainerColor getRandomContainerColor() {
		int rand = rnd.nextInt(6);
		switch(rand){
		case 0:
			return ContainerColor.ORGANIC;
		case 1:
			return ContainerColor.PAPER;
		case 2:
			return ContainerColor.PLASTICS;
		case 3:
			return ContainerColor.VIDRE;
		case 4:
			return ContainerColor.RESTA;
		default:
			return ContainerColor.PUNT_VERD;
		}
	}

	public void drawScene(Canvas canvas){
		synchronized (this) {			
			for(AbstractModelElement ame : elements){
				ame.draw(canvas);
			}
			for(AbstractModelElement ame : animations){
				ame.draw(canvas);
			}
			for(AbstractModelElement ame : containers){
				ame.draw(canvas);
			}
		}
		Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		paint.setTextSize(25f);
		paint.setColor(-1);
		canvas.drawText(gastCO2 + "gCO2", (float) (containers.get(0).getCanvasWidth() - 140), 150f, paint);
		canvas.drawText(estalviEuros + "€", (float) (containers.get(0).getCanvasWidth() - 140), 
				(float)(containers.get(0).getCanvasHeight() - 150f), paint);
	}

	public void updatePhysics() {
		synchronized (this) {
			List<AbstractModelElement> toBeRemoved = new ArrayList<AbstractModelElement>();
			for(AbstractModelElement a : elements){
				a.updatePhysics();
				//Check for container found.
				if (containerHit(a)) {

					toBeRemoved.add(a);
				}
			}
			for(AbstractModelElement a : animations){
				a.updatePhysics();
				if(a.getX() - a.getWidth()/2 > a.getCanvasWidth()){
					toBeRemoved.add(a);
				}
			}
			for(AbstractModelElement a : toBeRemoved){
				elements.remove(a);
				animations.remove(a);
			}
		}
	}

	public void touchDown(int x, int y) {
		if(!gameOn){
			return;
		}
		synchronized(this){
			for(AbstractModelElement a : elements){
				if(a.hit(x,y)){
					selected = a;
					a.touchDown(x,y);
					break;
				}
			}
		}
	}

	public void touchMove(int x, int y) {
		if(!gameOn){
			return;
		}
		synchronized(this){
			if(selected != null){
				selected.touchMove(x,y);
				//Check for container found.
				if(containerHit(selected)){
					selected = null;
					elements.remove(selected);
				}
			}
		}
	}

	private boolean containerHit(AbstractModelElement element) {
		for(ContainerModelElement container : containers){
			if(container.contains(element)){
				if(element.getContainerColor() == container.getContainerColor()){
					correctContainer(element,container);
					return true;
				}else{
					wrongContainer(element,container);
					return true;
				}
			}
		}
		return false;
	}

	private void wrongContainer(AbstractModelElement element, ContainerModelElement container) {
		synchronized(this){
			AnimationModelElement animation = new AnimationModelElement(context, element.getView(), element.getContainerColor(), false);
			animation.initialize();
			animation.setX(element.getX());
			animation.setY(element.getY());
			animation.setVelocityX(-1000);
			animation.setVelocityY(0);
			animations.add(animation);
			gastCO2 += element.getCO2FingerPrint();
			estalviEuros -= element.getDespesaGestioImpropis();
		}
	}

	private void correctContainer(AbstractModelElement element, ContainerModelElement container) {
		synchronized(this){
			AnimationModelElement animation = new AnimationModelElement(context, element.getView(), element.getContainerColor(), true);
			animation.initialize();
			animation.setX(element.getX());
			animation.setY(element.getY());
			animation.setVelocityX(-1000);
			animation.setVelocityY(0);
			animations.add(animation);
			gastCO2 -= element.getCO2Saving();
			estalviEuros += element.getEstalviEuros();
		}
	}

	public void touchUp() {
		if(!gameOn){
			return;
		}
		synchronized(this){
			if(selected != null){
				selected.touchUp();
				selected = null;
			}
		}
	}

}
